﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using YJKGeometryFuncs;

namespace YJKRevitStairs.HYElevator.Kit
{
	internal class FilterWallByLayerAndLine
	{
		internal Dictionary<ElementId, List<WallLocation>> DicWallEachLayer
		{
			get
			{
				return this.m_DicWallEachLayer;
			}
			set
			{
				this.m_DicWallEachLayer = value;
			}
		}

		public FilterWallByLayerAndLine(Autodesk.Revit.DB.Document Doc, List<ViewPlan> FloorPlan, Line SelLine)
		{
			this.m_Doc = Doc;
			this.GetMinAndMaxPt(SelLine);
			this.m_FloorPlan = FloorPlan;
		}

		public void Execute()
		{
			this.DicWallEachLayer = new Dictionary<ElementId, List<WallLocation>>();
			ElementClassFilter elementClassFilter = new ElementClassFilter(typeof(Wall));
			foreach (ViewPlan viewPlan in this.m_FloorPlan)
			{
				double elevation = viewPlan.GenLevel.Elevation;
				double upperLayerElavator = this.GetUpperLayerElavator(viewPlan);
				XYZ xyz = this.m_MinPt + new XYZ(0.0, 0.0, elevation);
				XYZ xyz2 = this.m_MaxPt;
				xyz2 += new XYZ(0.0, 0.0, upperLayerElavator);
				LogicalAndFilter logicalAndFilter = new LogicalAndFilter(new BoundingBoxIntersectsFilter(new Outline(xyz, xyz2)), elementClassFilter);
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Doc, viewPlan.Id);
				filteredElementCollector.WherePasses(logicalAndFilter).WhereElementIsNotElementType();
				List<WallLocation> list = new List<WallLocation>();
				foreach (Element element in filteredElementCollector)
				{
					Wall wall;
					if ((wall = (element as Wall)) != null)
					{
						Curve curve = (wall.Location as LocationCurve).Curve;
						double z = curve.GetEndPoint(0).Z;
						double val = 0.0;
						double num = 0.0;
						FilterWallByLayerAndLine.GetWallTopAndBottomElevator(this.m_Doc, element.Id, ref val, ref num);
						if (!Geometry.LessThan(elevation, val) && Geometry.GreaterThan(num - elevation, 1.0))
						{
							WallLocation item;
							item.WallId = wall.Id;
							Transform transform = Transform.CreateTranslation(XYZ.BasisZ * (elevation - z));
							item.curve = curve.CreateTransformed(transform);
							list.Add(item);
						}
					}
				}
				this.DicWallEachLayer.Add(viewPlan.GenLevel.Id, list);
			}
		}

		private double GetUpperLayerElavator(Autodesk.Revit.DB.View SelView)
		{
			int index = 0;
			double val = double.MaxValue;
			for (int i = 0; i < this.m_FloorPlan.Count; i++)
			{
				if (!(SelView.Id == this.m_FloorPlan[i].Id))
				{
					double num = this.m_FloorPlan[i].GenLevel.Elevation - SelView.GenLevel.Elevation;
					if (Geometry.GreaterThan(num, 0.0) && Geometry.GreaterThan(val, num))
					{
						index = i;
						val = num;
					}
				}
			}
			if (Geometry.Greaterthan_Or_Equal(SelView.GenLevel.Elevation, this.m_FloorPlan[index].GenLevel.Elevation))
			{
				return SelView.GenLevel.Elevation + 10.0;
			}
			return this.m_FloorPlan[index].GenLevel.Elevation;
		}

		private void GetMinAndMaxPt(Line SelLine)
		{
			XYZ endPoint = SelLine.GetEndPoint(0);
			XYZ endPoint2 = SelLine.GetEndPoint(1);
			double num = this.GetMinOrMaxValue(endPoint.X, endPoint2.X, true);
			double minOrMaxValue = this.GetMinOrMaxValue(endPoint.X, endPoint2.X, false);
			if (Geometry.IsEqual(num, minOrMaxValue, 0.001))
			{
				num -= 1.0;
			}
			double num2 = this.GetMinOrMaxValue(endPoint.Y, endPoint2.Y, true);
			double minOrMaxValue2 = this.GetMinOrMaxValue(endPoint.Y, endPoint2.Y, false);
			if (Geometry.IsEqual(num2, minOrMaxValue2, 0.001))
			{
				num2 -= 1.0;
			}
			this.m_MinPt = new XYZ(num, num2, 0.0);
			this.m_MaxPt = new XYZ(minOrMaxValue, minOrMaxValue2, 0.0);
		}

		private double GetMinOrMaxValue(double value1, double value2, bool isMin = true)
		{
			if (Geometry.LessThan(value1, value2))
			{
				if (isMin)
				{
					return value1;
				}
				return value2;
			}
			else
			{
				if (isMin)
				{
					return value2;
				}
				return value1;
			}
		}

		public static void GetWallTopAndBottomElevator(Autodesk.Revit.DB.Document Doc, ElementId wallid, ref double baseLevelValue, ref double topLevelValue)
		{
			Wall wall = Doc.GetElement(wallid) as Wall;
			ElementId elementId = wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).AsElementId();
			Level level = Doc.GetElement(elementId) as Level;
			double num = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).AsDouble();
			double num2 = wall.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).AsDouble();
			baseLevelValue = level.Elevation + num;
			topLevelValue = baseLevelValue + num2;
		}

		private Document m_Doc;

		private List<ViewPlan> m_FloorPlan;

		private Dictionary<ElementId, List<WallLocation>> m_DicWallEachLayer;

		private XYZ m_MinPt;

		private XYZ m_MaxPt;
	}
}
